
'use strict';


const  electron = require('electron');
const { app, Menu, BrowserWindow } = electron;

const logger = require( 'winston');
const path = require( 'path' );
const os = require( 'os' );
const fs = require('fs');

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
var mainWindow = null;
var windowBounds = new Array();
var graphName;
var isReload = false;

var FILE_UTILS = new NodeFileUtils();

function NodeFileUtils () {
  this.getLastUpdatedTime = function( resourcePath ) {
    var latestFileTime = 0;

    var fileNames = fs.readdirSync( resourcePath );
    if ( fileNames == null || fileNames.length == 0 ) return latestFileTime;
    fileNames.forEach( function( fileName ) {
      var fullPath = path.join( resourcePath, fileName );
      var stats = fs.statSync( fullPath );
      var fileOrDirectoryUpdateTime = 0;
      if ( stats.isFile() ) {
        fileOrDirectoryUpdateTime = stats.mtime.getTime();
      } else if ( stats.isDirectory() ) {
        fileOrDirectoryUpdateTime = this.getLastUpdatedTime( fullPath );
      }
      if ( fileOrDirectoryUpdateTime > latestFileTime ) latestFileTime = fileOrDirectoryUpdateTime;
    }.bind( this ));

    return latestFileTime;
  };



}

// Quit when all windows are closed.
app.on('window-all-closed', function() {
  // On OS X it is common for applications and their menu bar
  // to stay active until hte user quits explicitly with Cmd + Q
  if (process.platform != 'darwin') {
    app.quit();
  }
});


function PilotFileCleanup( inMaxFiles ) {
  this.maxFiles = inMaxFiles;

  /**
   * Initialize the directory if it doesn't exist...roll the files if it does
   * <B>Not, one level of directory nesting please, this is not mkdirp</B>
   * @param path
   */
  this.init = function( logLocation ) {
    var directoryName = path.dirname( logLocation );
    console.log( "Initializing Log at ", logLocation);
    if ( !fs.existsSync( directoryName ) ) {
      fs.mkdirSync( directoryName );
    } else if ( fs.existsSync( logLocation ) ) {
      //rolling
      this.roll( logLocation );
    }
  }

  this.leftPad = function( value ) {
    if ( value.toString().length < 2 ) return "0" + value.toString();
    return value;
  }

  /**
   * Make sure we have one less file that starts with our prefix
   * from the this.maxFile
   */
  this.prune = function ( logFile ) {
    var directoryName = path.dirname( logFile );
    var fileName = path.basename( logFile );
    var files = fs.readdirSync( directoryName );
    if ( files == null ) return;
    var matched = 0;
    files.forEach( function( file ) {
      if ( file.startsWith( fileName ) ) {
        matched++;
        if ( matched >= inMaxFiles ) {
          var joinedName = path.join( directoryName, file );
          console.log( "Removing: ", joinedName );
          fs.unlinkSync( joinedName );
        }
      }
    });

  }

  this.roll = function( path ) {
    this.prune( path );
    var today = new Date();
    var suffix = today.getFullYear()+"-" + this.leftPad( today.getMonth() ) + "-" + this.leftPad( today.getDay() );
    suffix = suffix + "-" + this.leftPad( today.getHours() ) +"." + this.leftPad( today.getMinutes() )+"." + this.leftPad( today.getSeconds() );
    var rolledPathName = path + "." + suffix;
    console.log( "Rolling LogFile to ", rolledPathName );
    fs.renameSync( path, rolledPathName );
  }
}



var PILOT_FILE_CLEANUP = new PilotFileCleanup( 10 );

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {    
  console.log( process.argv );
  //var data;
  var electronScreen;
  var queryString = "";
  var frame = true;
  var boundSet = false;
  var sendConfig = false;
  var overrideHostPort = null;
  var data = {
    bounds: {width: 600, height: 450, x: 10, y:10, frame: false },
    name: {}
  } 



  for(var i=0; i < process.argv.length; i++) {
      var arr = process.argv[i].split(' ');      
      if (arr.length == 2) {
          if (arr[0] == "--name") {
              data.name = arr[1];
              graphName = arr[1];
          } else if (arr[0] == "--queryString") {
              queryString = "?" + arr[1]; 
          } else if (arr[0] == "--frameless") {
              frame = !getBoolean(arr[1])
          } else if (arr[0] == "--xpos") {            
              data.bounds.x = parseInt(arr[1]);
              boundSet = true;
          } else if (arr[0] == "--ypos") {
              data.bounds.y = parseInt(arr[1]);
              boundSet = true;
          } else if (arr[0] == "--height") {
              data.bounds.height = parseInt(arr[1]);
              boundSet = true;
          } else if (arr[0] == "--width") {
              data.bounds.width = parseInt(arr[1]);
              boundSet = true;
          } else if (arr[0] == "--sendConfig") {
              sendConfig = true;
          } else if (arr[0] == "--overrideHost") {
              overrideHostPort = arr[ 1  ];
          }
            
      }
  }
  data.bounds.frame = frame;
  
//   if ( process.argv.length >= 1 ) {
//     queryString = "?";
//     var argumentIndex = process.argv.length >= 3 ? 2 : 1;
//     queryString = queryString +  process.argv[ argumentIndex ];
//   }
  if ( !graphName ) {
    graphName = "chartConfig.json";
  }
  queryString = queryString + "&" + "name=" + graphName;
  var logFilePath =  path.join( os.homedir(), "/pilotgraph/"+normalizeFileName(graphName)+".log"  );
  PILOT_FILE_CLEANUP.init( logFilePath );

  console.log( "Parameters received: " + queryString );
  console.log( "homedir ", os.homedir(), "joined: " , logFilePath );
  // logger.remove(logger.transports.Console);
  logger.add(logger.transports.File, { filename: logFilePath });
  logger.exitOnError = false;
  logger.info( "test");
  global.logger = logger;


  electronScreen = electron.screen;
  if (!boundSet){
    loadBounds(graphName);
    data = getBounds(graphName, frame)    
  }
  //var size = electronScreen.getPrimaryDisplay().workAreaSize;

  // Create the browser window.
  mainWindow = new BrowserWindow({
    autoHideMenuBar: true,
    frame: data.bounds.frame,
    width: data.bounds.width,
    height: data.bounds.height,
    show: false,
    useContentSize: true,
    maximizable: false,
    x: data.bounds.x,
    y: data.bounds.y,
    //title: data.bounds.name,
    //icon: "C:\\Users\\ppatel\\Desktop\\pilot icons\\pilot_large_img.png",
    webPreferences: {
      nodeIntegration: true
      }
    });
  var lastUpdateTime = FILE_UTILS.getLastUpdatedTime(  app.getAppPath() );
  if ( !queryString.startsWith( "?" ) ) queryString = "?" + queryString;

  // and load the index.html of the app.
  var urlStr = 'file://' + __dirname + '/index.html' + queryString + "&lastUpdateTime=" + lastUpdateTime;
  mainWindow.loadURL(urlStr) ;


  // Open the DevTools.
  //mainWindow.webContents.openDevTools();

  buildMenu();
  var wc = mainWindow.webContents;
  wc.on("did-finish-load", function(event) {
    console.log("Finish loading url: " + urlStr);
    var config;
    if ( graphName != "chartConfig.json" ) {
      config = loadFromFile("graphconfig", graphName);
    } else {
      console.log( "attempting to load chartConfig.json from the current directory, no graph name provided and automatically send config to chart." );
      var fs = require("fs");
      config = JSON.parse( fs.readFileSync( "./chartConfig.json", "utf8") );
      sendConfig = true;
    }
    
    if ( typeof config != "undefined" && sendConfig ) {
      if ( overrideHostPort != null ) {
        var parts = overrideHostPort.split( ":" );
        config.host = parts[0];
        config.port = parts[1];
        config.urls = [ overrideHostPort ];
      }
      var jsCall = 'processConfig ('+ JSON.stringify(config) + ');';
      console.log("Executing: ", jsCall );
     // wc.executeJavaScript(jsCall);

    }
  });
  mainWindow.showInactive();
  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
  
  
  mainWindow.on('move', function() {
    saveWindowSizeAndLocation();
  });  

  mainWindow.on('resize', function() {
    saveWindowSizeAndLocation();
  });  
});

function getBoolean( value ) {
  if ( value == null ) return false;
  if ( typeof value == "boolean" ) return value;
  else return value.toLowerCase() == "true";
}

function normalizeFileName(fileName){
	return fileName.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g,'_');
}
	
function saveSizePosition() {
    saveWindowSizeAndLocation();
}

function saveWindowSizeAndLocation() {
    var data = {
      bounds: mainWindow.getBounds(),
      name: graphName
    };
    writeWindowSize(graphName, data);    
}

exports.reload = function() {
    isReload = true;
    mainWindow.reload();
}

function getWindowSize(name, f) {
    var oldData;
    for(var i=0; i < windowBounds.length; i++) {
        oldData = windowBounds[i];
        if (oldData && oldData.name == name) {
            return oldData;
        }
    }
    return null;
}

function writeWindowSize(name, data) {

    var oldData;
    for(var i=0; i < windowBounds.length; i++) {
        if (windowBounds[i] && windowBounds[i].name == name) {
            oldData = windowBounds[i];
            oldData.bounds = data.bounds;
        }
    }
    if (!oldData) {
      windowBounds[i] = data;
    }

    var d = path.join(app.getPath( "appData" ), "graphwin");

    try {
        fs.mkdirSync(d);
    } catch(e) {
        if ( e.code != 'EEXIST' ) throw e;
    }    

    var initPath = d + "/" + normalizeFileName(name) + ".json";
    var jsonStr = JSON.stringify(windowBounds);
    fs.writeFileSync(initPath, jsonStr);
    console.info("Written window size to " + initPath);
}

function loadBounds(name) {
  var path = require("path");
  var fs = require("fs");
  var initPath = path.join(app.getPath( "appData" ), "graphwin/" + normalizeFileName(name) + ".json");
  console.info("Reading window size from " + initPath);
  try {
    windowBounds = JSON.parse(fs.readFileSync(initPath, 'utf8'));
  }
  catch(e) {
  }    
}

function getLastNewWindowPos(f) {
  var path = require("path");
  var fs = require("fs");
  var d = path.join( app.getPath( "appData" ), "graphwin");    
  try {
    fs.mkdirSync(d);
  } catch(e) {
    if ( e.code != 'EEXIST' ) throw e;
  }      
  var initPath = path.join(d, "/lastWinPos.json");
  console.info("Reading last window from " + initPath);
  var bounds;
  try {
    bounds = JSON.parse(fs.readFileSync(initPath, 'utf8'));
  }
  catch(e) {
  }    
  if (!bounds) {
      bounds = {width: 600, height: 450, x: 10, y:10, frame: f }; 
  } else {
      if (bounds.x > 300) {
          bounds.x = 10;
      } else {
          bounds.x += 30;
      }
      if (bounds.y > 300) {
          bounds.y = 10;
      } else {
          bounds.y += 30;
      }
  }
  bounds.frame = f;
  var jsonStr = JSON.stringify(bounds);
  fs.writeFileSync(initPath, jsonStr);
  return bounds  
}

function getBounds(name, f) {
  if (!name) {
    return {
        bounds : {width: 600, height: 450, x: 10, y:10, frame: f }
    };
  }
  var data = getWindowSize(graphName, f);
  if (!data) {
    data = {
      bounds : getLastNewWindowPos(f),
      name : graphName
    };  
    writeWindowSize(graphName, data);    
  }
  data.bounds.frame = f;
  return data;
}

exports.getGraphConfig = function(name) {
    return loadFromFile("graphconfig", name);    
}

exports.saveGraphConfig = function(name, config) {
    saveToFile("graphconfig", name, JSON.stringify(config));
}

exports.setBounds = function(bounds) {
    mainWindow.setBounds(bounds);
}

function saveToFile(dirName, fileName, jsonStr) {
    var path = require("path");
    var fs = require("fs");
    var d = path.join( app.getPath( "appData" ), dirName);    

    try {
        fs.mkdirSync(d);
    } catch(e) {
        if ( e.code != 'EEXIST' ) throw e;
    }    

    var initPath = d + "/" + normalizeFileName(fileName) + ".json";
    fs.writeFileSync(initPath, jsonStr);
    console.info("Written to " + initPath + " json: " + jsonStr);        
}

function loadFromFile(dirName, fileName) {
    var path = require("path");
    var fs = require("fs");
    var d = path.join( app.getPath( "appData" ), dirName);    
    try {
        fs.mkdirSync(d);
    } catch(e) {
        if ( e.code != 'EEXIST' ) throw e;
    }      
    var initPath = d + "/" + normalizeFileName(fileName) + ".json";
    var json;
    try {
        json = JSON.parse(fs.readFileSync(initPath, 'utf8'));
    }
    catch(e) {
    }        
    logger.info("Read from " + initPath + " json: " + json);
    return json;
}

function buildMenu() {
  var template = [
    {
      label: 'View',
      submenu: [
        {
          label: 'Reload',
          accelerator: 'Alt+Command+R',
          click: function() { 
            isReload = true;
            mainWindow.reload();              
          }
        },
        {
          label: 'Toggle DevTools',
          accelerator: 'Alt+Command+I',
          click: function() {
            console.log("Toggle DevTools");
            if (mainWindow.webContents.isDevToolsOpened()) {
              mainWindow.webContents.closeDevTools();
            } else {
              mainWindow.webContents.openDevTools();
            }
          }
        },
      ]
    },
    {
      label: 'Help',
      submenu: []
    }
  ];

  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
}
